Use Case 1: face_recognition¶


Contents¶

I. Mannual Process¶

  • Demonstrating how we can conduct the facial recognition process manually

II. Automate the Process¶

  • By encoding all the images and wrap all the distance calculation in a function, this step shows how we can automate the entire facial comparision process

III. Performance Evaluation¶

  • After conducting all the facial comparision in the previous step, we can evaluate the outcomes, and assess the performance of the library on our images.

IV. Examples¶

  • Display some facial comparision along with their similarities. These examples contains expected matches and expected non-matches

I. Mannual Process¶

In this manual process, I am going to demonstrate the manual way to compare two faces.

In [ ]:
import pandas as pd
import numpy as np
import subprocess
import sys
import matplotlib.pyplot as plt
import seaborn as sns
import face_recognition
from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageOps, ImageEnhance
import os
import pickle
from sklearn.metrics import confusion_matrix, accuracy_score, precision_score, recall_score
In [ ]:
# import image to python and load the image
image_file = '2024_students/Boyan_Wei_aged.jpg'
image = Image.open(image_file)

# resize the image
width , height = image.size
print('Original image size: ', width, height)
image = image.resize((int(width/4), int(height/4)))

# new size of the image
width , height = image.size
print('New image size: ', width, height)

# display the image
display(image)
Original image size:  1024 1024
New image size:  256 256
No description has been provided for this image

Loop over the excel file to obtain the names of all images in the msba folder

In [ ]:
match_file = pd.read_excel('image_name.xlsx')

# eyeball the dataset
match_file.head()
Out[ ]:
match_id source_image name target_image expected_match
0 100 Bingyu_Li.jpg Bingyu_Li Bingyu_Li_aged.jpg match
1 101 Whitney_Joyce_Isbell.jpg Whitney_Joyce_Isbell Whitney_Joyce_Isbell_aged.jpg match
2 102 Qian_Chen.jpg Qian_Chen Qian_Chen_aged.jpg match
3 103 Hanshuai_Shi.jpg Hanshuai_Shi Hanshuai_Shi_aged.jpg match
4 104 Ruochen_Bao.jpg Ruochen_Bao Ruochen_Bao_aged.jpg match

I would like to display the two faces next to each other, and place the similarity in the middle

In [ ]:
def display_compare_face(image_file, match_file):
    """

    Args:
        image_file: image to be compared (shown on the left)
        match_file: image to be compared with (shown on the right)
    return:
        display the two images side by side with its similarity score
    """

    image1 = face_recognition.load_image_file(image_file)
    image2 = face_recognition.load_image_file(match_file)

    # calculate the distance between the two faces
    img1_encoding = face_recognition.face_encodings(image1)[0]
    img2_encoding = face_recognition.face_encodings(image2)[0]
    face_distance = face_recognition.face_distance([img1_encoding], img2_encoding)
    # normalize the distance to get the similarity score 
    similarity = 1 - face_distance[0]
    image1 = Image.open(image_file)
    image2 = Image.open(match_file)

    # Resize the second image to match the first image's size
    image1 = image1.resize(image2.size)

    # Create a new blank image with a size equal to the sum of the widths of the two images

    new_image_width = image1.width * 2

    new_image_height = image1.height

    new_image = Image.new("RGB", (new_image_width, new_image_height))

    # Paste the first image onto the new image at position (0, 0)

    new_image.paste(image1, (0, 0))

    # Paste the second image onto the new image at position (image1.width, 0)

    new_image.paste(image2, (image1.width, 0))

    # Add text to the image
    text = '{} % MATCH'.format(int(similarity*100))
    font_path = "2024_students/Roboto-Medium.ttf"  # Ensure this path is correct
    font = ImageFont.truetype(font_path, size=48)
    draw = ImageDraw.Draw(new_image)

    # Calculate the text position
    # text_width, text_height = draw.textsize((0,0), text, font)
    left, top, right, bottom = draw.textbbox((0,0), text, font)
    text_width = right - left
    text_height = bottom - top
    text_x = (new_image_width - text_width)/2
    text_y = (new_image_height - text_height)/2

    # Draw the text over the rectangle
    draw.text((text_x, text_y), text, font=font, fill=(0, 0, 0, 255))

    # display the image
    display(new_image)
        
In [ ]:
# 1. Load two images using load_image_file
face_file1 = "2024_students/Boyan_Wei.jpg"
face_file2 = "2024_students/Boyan_Wei_aged.jpg"
image1 = face_recognition.load_image_file(face_file1)
image2 = face_recognition.load_image_file(face_file2)
In [ ]:
# 2. Compare the face_encodings similarity using face_distance
img1_encoding = face_recognition.face_encodings(image1)[0]
img2_encoding = face_recognition.face_encodings(image2)[0]

# Calculate the distance between the faces
face_distance = face_recognition.face_distance([img1_encoding], img2_encoding)

# Normalize the distance to get the similarity score
similarity = 1 - face_distance[0]

# Print the similarity score
print("The two faces are '{:.2f}%' similar".format(similarity*100))
The two faces are '66.68%' similar
In [ ]:
# 3. is it a match?
face_matches = face_recognition.compare_faces([img1_encoding], img2_encoding) # default threshold is 0.6

# Print the result
if face_matches[0]:
    print("The two faces match")
else:
    print("The two faces do not match")
The two faces match
In [ ]:
# Open the two image files
image1 = Image.open(face_file1)
image2 = Image.open(face_file2)

# Resize the second image to match the first image's size
image1 = image1.resize(image2.size)

# Create a new blank image with a size equal to the sum of the widths of the two images

new_image_width = image1.width * 2

new_image_height = image1.height

new_image = Image.new("RGB", (new_image_width, new_image_height))

# Paste the first image onto the new image at position (0, 0)

new_image.paste(image1, (0, 0))

# Paste the second image onto the new image at position (image1.width, 0)

new_image.paste(image2, (image1.width, 0))

# Add text to the image
text = '{} % MATCH'.format(int(similarity*100))
font_path = "2024_students/Roboto-Medium.ttf"  # Ensure this path is correct
font = ImageFont.truetype(font_path, size=48)
draw = ImageDraw.Draw(new_image)

# Calculate the text position
# text_width, text_height = draw.textsize((0,0), text, font)
left, top, right, bottom = draw.textbbox((0,0), text, font)
text_width = right - left
text_height = bottom - top
text_x = (new_image_width - text_width)/2
text_y = (new_image_height - text_height)/2

# Draw the text over the rectangle
draw.text((text_x, text_y), text, font=font, fill=(0, 0, 0, 255))

# display the image
display(new_image)
No description has been provided for this image

II. Automate the Process¶


List all the "images" from our cohort and put them in one list

In [ ]:
dir_name = '2024_students'
def list_jpeg_files(directory):
    """List all JPEG files in the specified directory."""
    jpeg_files = [file for file in os.listdir(directory) if file.lower().endswith(('.jpeg', '.jpg'))]
    return jpeg_files

directory_path = './2024_students'
jpeg_files = list_jpeg_files(directory_path)

print("JPEG files in the directory:", jpeg_files)
JPEG files in the directory: ['Dongqiao_Tang_aged.jpg', 'Hewei_Shen_aged.jpg', 'Jackson_R_Harper_aged.jpg', 'Wei_Tan.jpg', 'Nathanael_Hunter_Kraus.jpg', 'Benjamin_Pyung-Hwa_Aikens_aged.jpg', 'Helen_Kidane_Haile_aged.jpg', 'Samantha_O_Brien_aged.jpg', 'Yiming_Xu_aged.jpg', 'Manling_Shi_aged.jpg', 'Meghan_O_Malley.jpg', 'Eric_Mayo.jpg', 'Haopeng_Liu.jpg', 'Wei_Tan_aged.jpg', 'Jennifer_Ontiveros-Olivas.jpg', 'Nicholas_J_Sundberg_aged.jpg', 'Patrick_Ryan_Weimaker.jpg', 'Zihe_Liu_aged.jpg', 'Manling_Shi.jpg', 'Amanda_Renner_Gild_aged.jpg', 'George_Basil_Economus.jpg', 'Michelle_Monica_Saikali.jpg', 'Joseph_Macon_Barker.jpg', 'Kaitlyn_R_Vickers_aged.jpg', 'Andrea_Chen.jpg', 'Kyle_John_Wiblishauser.jpg', 'Skylour_Sebastian_Winakur.jpg', 'Logan_Trujillo.jpg', 'Xingyu_Wan.jpg', 'Cole_Ritchey_aged.jpg', 'Jiacheng_Wang_aged.jpg', 'Garhett_William_Sessions_aged.jpg', 'Kendall_Ashley_Hilson_aged.jpg', 'Kayla_Marie_Williams_aged.jpg', 'Kaushik_Rajaram_aged.jpg', 'Latham_Alexander_Weaver_aged.jpg', 'Trinity_Nicole_Elliott_aged.jpg', 'Reid_Powers_Walker_aged.jpg', 'Bingnan_Lei_aged.jpg', 'Andrea_Chen_aged.jpg', 'Savannah_Kayla_Littlejohn_aged.jpg', 'Jash_Sanjaybhai_Vachhani_aged.jpg', 'Elizabeth_G_Higgins_aged.jpg', 'Estefani_Santiago_Gatica_aged.jpg', 'Qin_Miao_aged.jpg', 'Yue_Zhou_aged.jpg', 'Niklas_Jozef_Baldis_aged.jpg', 'Hanshuai_Shi.jpg', 'Edward_Cheongjoun_Hyun_aged.jpg', 'Christopher_Craig_Kenney.jpg', 'Xiyan_Huang.jpg', 'Lauren_Elizabeth_Johnson_aged.jpg', 'Angela_Waszkiewicz.jpg', 'Tianyu_Cui.jpg', 'Jiaming_Zhang_aged.jpg', 'Xiaoya_Luo_aged.jpg', 'Nathalie_Lisa_Friedman_aged.jpg', 'Shenger_Zhou_aged.jpg', 'Jiahua_Wu.jpg', 'Hewei_Shen.jpg', 'Andrew_Dubois.jpg', 'Emmanuel_Thomas_George_Skora.jpg', 'John_William_Null_aged.jpg', 'Bingyu_Li.jpg', 'Jodie_Elizabeth_Brine.jpg', 'Meryl_Criswell_Kaduboski.jpg', 'Amanda_Renner_Gild.jpg', 'Michael_Jason_Vejsiri_aged.jpg', 'Patrick_Ryan_Weimaker_aged.jpg', 'Zihe_Liu.jpg', 'Emmanuel_Thomas_George_Skora_aged.jpg', 'Daniel_Madden_Sheedy_aged.jpg', 'Zaul_Alexander_Perez_aged.jpg', 'Lu_Xing_aged.jpg', 'Niklas_Jozef_Baldis.jpg', 'Kendall_Ashley_Hilson.jpg', 'Shenzhe_Lian_aged.jpg', 'Dillon_Hunter_Aryeh_aged.jpg', 'Nathanael_Hunter_Kraus_aged.jpg', 'Tianyi_Yin_aged.jpg', 'Cole_Ritchey.jpg', 'Bingnan_Lei.jpg', 'Zaul_Alexander_Perez.jpg', 'Max_Koontz.jpg', 'Yiming_Xu.jpg', 'Evan_Anderson_Gilbert.jpg', 'Xiyue_Yu_aged.jpg', 'Cheuk_Yui_Marcus_Chan_aged.jpg', 'Shuzhe_Wang_aged.jpg', 'Helen_Kidane_Haile.jpg', 'Harve_E_Criqui.jpg', 'Khushi_Arya_aged.jpg', 'Anne_M_Perry_aged.jpg', 'Jash_Sanjaybhai_Vachhani.jpg', 'George_Basil_Economus_aged.jpg', 'Mary_Michele_Troise_aged.jpg', 'Samantha_O_Brien.jpg', 'Boyan_Wei_aged.jpg', 'Luying_Huang_aged.jpg', 'Meghan_O_Malley_aged.jpg', 'Alfredo_Enrique_Suarez_aged_aged.jpg', 'Boyu_Zheng.jpg', 'Quinn_Poole.jpg', 'Daniel_Madden_Sheedy.jpg', 'Guangxin_Bao.jpg', 'Tianyi_Chen.jpg', 'Andrew_Dubois_aged.jpg', 'Ryan_Marek_Smith.jpg', 'Dillon_Hunter_Aryeh.jpg', 'Meryl_Criswell_Kaduboski_aged.jpg', 'Chioke_K_Bellamy_aged.jpg', 'Marcus_Cole_cooper.jpg', 'Harve_E_Criqui_aged.jpg', 'Anthony_X_Ayala.jpg', 'Nathalie_Lisa_Friedman.jpg', 'Bintong_Zhai_aged.jpg', 'Quinn_Poole_aged.jpg', 'Logan_Trujillo_aged.jpg', 'Savannah_Kayla_Littlejohn.jpg', 'Christopher_Craig_Kenney_aged.jpg', 'Ryan_Marek_Smith_aged.jpg', 'Bryce_Charles_Drynan_aged.jpg', 'Nicolson_Charles_Panos_aged.jpg', 'Yuchen_Qin_aged.jpg', 'Marcus_Cole_cooper_aged.jpg', 'Xiaoyu_Zong_aged.jpg', 'Shuzhe_Wang.jpg', 'Songlin_Liu.jpg', 'Boyu_Zheng_aged.jpg', 'Ruochen_Bao_aged.jpg', 'Millie_C_Garrett.jpg', 'Chengzhan_Shen.jpg', 'Xiaoyang_Zheng.jpg', 'Allen_Gail_Smith.jpg', 'Reid_Powers_Walker.jpg', 'Jeremy_Brian_Nurding_aged.jpg', 'Qian_Chen.jpg', 'Yutong_Ouyang.jpg', 'Natalie_Weiner_aged.jpg', 'Alfredo_Enrique_Suarez_aged.jpg', 'Edward_Cheongjoun_Hyun.jpg', 'Alicia_Rand_Bodoia.jpg', 'Millie_C_Garrett_aged.jpg', 'Whitney_Joyce_Isbell_aged.jpg', 'Hangfei_Lyu_aged.jpg', 'Angela_Waszkiewicz_aged.jpg', 'Shenzhe_Lian.jpg', 'Shenghao_Yang.jpg', 'Yilin_Wang_aged.jpg', 'Andrew_Lloyd_Loftis_aged.jpg', 'Jennifer_Ontiveros-Olivas_aged.jpg', 'Kaushik_Rajaram.jpg', 'Shenger_Zhou.jpg', 'Yanghua_Zhang_aged.jpg', 'Latham_Alexander_Weaver.jpg', 'Jacob_Philip_Rockaway.jpg', 'Khushi_Arya.jpg', 'Skylour_Sebastian_Winakur_aged.jpg', 'Jiahao_Ma_aged.jpg', 'Yutong_Ouyang_aged.jpg', 'Jeremy_Brian_Nurding.jpg', 'Raleigh_Coolidge_Conway.jpg', 'Andrew_Lloyd_Loftis.jpg', 'Ruochen_Bao.jpg', 'Kaamil_Farooqi.jpg', 'Songlin_Liu_aged.jpg', 'Jiahao_Ma.jpg', 'Garhett_William_Sessions.jpg', 'Hangfei_Lyu.jpg', 'Jackson_R_Harper.jpg', 'Michael_Jason_Vejsiri.jpg', 'Yuchen_Qin.jpg', 'Xiaoya_Luo.jpg', 'Cheuk_Yui_Marcus_Chan.jpg', 'Alfredo_Enrique_Suarez.jpg', 'Qin_Miao.jpg', 'Elizabeth_G_Higgins.jpg', 'Evan_Anderson_Gilbert_aged.jpg', 'Sebastian_Andres_Lopez-Ibanez.jpg', 'Natalie_Weiner.jpg', 'Jax_Francis_Revfi_aged.jpg', 'Shanay_Nimish_Sonawala_aged.jpg', 'Jax_Francis_Revfi.jpg', 'Mengyao_Liu_aged.jpg', 'Kaitlyn_R_Vickers.jpg', 'Jodie_Elizabeth_Brine_aged.jpg', 'Anthony_X_Ayala_aged.jpg', 'Shenghao_Yang_aged.jpg', 'Mary_Martha_Milcoff_aged.jpg', 'Christopher_David_Koontz_aged.jpg', 'Eric_Mayo_aged.jpg', 'Michelle_Monica_Saikali_aged.jpg', 'Kyle_John_Wiblishauser_aged.jpg', 'Xiyan_Huang_aged.jpg', 'Anoush_U_Shah_aged.jpg', 'Xingyu_Wan_aged.jpg', 'Hanshuai_Shi_aged.jpg', 'Lu_Xing.jpg', 'Wentong_Guo.jpg', 'Raleigh_Coolidge_Conway_aged.jpg', 'Yilin_Wang.jpg', 'Dongqiao_Tang.jpg', 'Kayla_Marie_Williams.jpg', 'Mengyao_Liu.jpg', 'Trinity_Nicole_Elliott.jpg', 'Siyu_Lin_aged.jpg', 'Max_Koontz_aged.jpg', 'Shanay_Nimish_Sonawala.jpg', 'Luying_Huang.jpg', 'Bintong_Zhai.jpg', 'Haopeng_Liu_aged.jpg', 'Kaamil_Farooqi_aged.jpg', 'Xiaoyu_Zong.jpg', 'Whitney_Joyce_Isbell.jpg', 'Nicholas_J_Sundberg.jpg', 'John_William_Null.jpg', 'Jiacheng_Wang.jpg', 'Tianyi_Yin.jpg', 'Lauren_Elizabeth_Johnson.jpg', 'Chengzhan_Shen_aged.jpg', 'Estefani_Santiago_Gatica.jpg', 'Alicia_Rand_Bodoia_aged.jpg', 'Boyan_Wei.jpg', 'Jiahua_Wu_aged.jpg', 'Allen_Gail_Smith_aged.jpg', 'Xiaoyang_Zheng_aged.jpg', 'Siyu_Lin.jpg', 'Mary_Michele_Troise.jpg', 'Nicolson_Charles_Panos.jpg', 'Tianyu_Cui_aged.jpg', 'Jiaming_Zhang.jpg', 'Xiyue_Yu.jpg', 'Mary_Martha_Milcoff.jpg', 'Bingyu_Li_aged.jpg', 'Benjamin_Pyung-Hwa_Aikens.jpg', 'Tianyi_Chen_aged.jpg', 'Guangxin_Bao_aged.jpg', 'Chioke_K_Bellamy.jpg', 'Joseph_Miller_Hirsch_aged.jpg', 'Anoush_U_Shah.jpg', 'Joseph_Miller_Hirsch.jpg', 'Sebastian_Andres_Lopez-Ibanez_aged.jpg', 'Joseph_Macon_Barker_aged.jpg', 'Christopher_David_Koontz.jpg', 'Bryce_Charles_Drynan.jpg', 'Jacob_Philip_Rockaway_aged.jpg', 'Wentong_Guo_aged.jpg', 'Anne_M_Perry.jpg', 'Yanghua_Zhang.jpg', 'Qian_Chen_aged.jpg', 'Yue_Zhou.jpg']

This process would take a lot of time. So I saved it to a pickle file and import it in whenever needed

In [ ]:
# face_dict = {}
# for file in jpeg_files:
#     # load image
#     img = face_recognition.load_image_file(f"./2024_students/{file}")
#     # detect faces in the image
#     face_locations = face_recognition.face_locations(img)
#     if len(face_locations) > 0:
#         # get encoding
#         enc = face_recognition.face_encodings(img)[0]
#         face_dict[file] = enc
#     else:
#         print(f"No face detected in {file}")

# Save the dictionary so we don't have to re-run the encoding step again 
# with open('face_dict.pickle', 'wb') as f:
#     pickle.dump(face_dict, f)

face_dict = {}
with open("face_dict.pickle", "rb") as f:
    face_dict = pickle.load(f)
In [ ]:
# convert to dataframe
data_items = list(face_dict.items())

# Create DataFrame
face_df = pd.DataFrame(data_items, columns=['image', 'encoding'])
face_df.head()
Out[ ]:
image encoding
0 Alfredo_Enrique_Suarez.jpg [-0.14946380257606506, -0.018561195582151413, ...
1 Alfredo_Enrique_Suarez_aged.jpg [-0.18067379295825958, -0.020742785185575485, ...
2 Alfredo_Enrique_Suarez_aged_aged.jpg [-0.16252249479293823, -0.035916682332754135, ...
3 Alicia_Rand_Bodoia.jpg [-0.04311027750372887, 0.021171540021896362, 0...
4 Alicia_Rand_Bodoia_aged.jpg [-0.0516541562974453, 0.08393877744674683, 0.1...
In [ ]:
# face match function
def match_faces(source_image, target_image):
    
    """
    Args:
        source_image: image to be matched against
        target_image: image to be matched

    Returns:
        similarity score between 0 and 100
    """
    
    if source_image in face_df['image'].values and target_image in face_df['image'].values:
        enc1 = face_df.loc[face_df['image'] == source_image, 'encoding'].iloc[0]
        enc2 = face_df.loc[face_df['image'] == target_image, 'encoding'].iloc[0]
        face_distance = face_recognition.face_distance([enc1], enc2)
        similarity = 1 - face_distance[0]
        return similarity * 100
    else:
        return None


match_faces('Alfredo_Enrique_Suarez.jpg','Alfredo_Enrique_Suarez_aged.jpg')
Out[ ]:
62.890925297757775

III. Performance Evaluation¶

In [ ]:
match_file['match_similarity'] = match_file.apply(lambda row: match_faces(row['source_image'], row['target_image']), axis=1)

Use a threshold of 50% to decide where the two face is a match or not.

In [ ]:
match_file['predicted_match'] = np.where(match_file['match_similarity'] > 50, 'match','no match')
In [ ]:
# Calculate confusion matrix
matrix = confusion_matrix(match_file['expected_match'],
                          match_file['predicted_match'],
                          labels=["match", "no match"])

print(matrix)
[[110  16]
 [  2  48]]
In [ ]:
# Calculate confusion matrix
y_true = match_file['expected_match']
y_pred = match_file['predicted_match']
labels = ["match", "no match"]
matrix = confusion_matrix(y_true, y_pred, labels=labels)
# specificity
specificity = matrix[1,1]/(matrix[1,0]+matrix[1,1])

# Calculate Accuracy, Precision and Recall
accuracy = accuracy_score(y_true, y_pred)
precision = precision_score(y_true, y_pred, pos_label="match")
recall = recall_score(y_true, y_pred, pos_label="match")

print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("Specificity:", specificity)
Accuracy: 0.8977272727272727
Precision: 0.9821428571428571
Recall: 0.873015873015873
Specificity: 0.96
In [ ]:
# Plotting using seaborn
plt.figure(figsize=(8, 6))
sns.heatmap(matrix, annot=True, fmt="d", xticklabels=labels, yticklabels=labels, cmap="Blues")
plt.title("Confusion Matrix of face_recognition open source library")
plt.ylabel('Actual')
plt.xlabel('Predicted')
plt.show()
No description has been provided for this image

Lower the threshold to 35

In [ ]:
match_file['predicted_match_35'] = np.where(match_file['match_similarity'] > 35, 'match','no match')
In [ ]:
# Calculate confusion matrix
matrix = confusion_matrix(match_file['expected_match'],
                          match_file['predicted_match_35'],
                          labels=["match", "no match"])

print(matrix)
[[118   8]
 [  3  47]]
In [ ]:
# Calculate confusion matrix
y_true = match_file['expected_match']
y_pred = match_file['predicted_match_35']
labels = ["match", "no match"]
matrix = confusion_matrix(y_true, y_pred, labels=labels)
# specificity
specificity = matrix[1,1]/(matrix[1,0]+matrix[1,1])

# Calculate Accuracy, Precision and Recall
accuracy = accuracy_score(y_true, y_pred)
precision = precision_score(y_true, y_pred, pos_label="match")
recall = recall_score(y_true, y_pred, pos_label="match")

print("Accuracy:", accuracy)
print("Precision:", precision)
print("Recall:", recall)
print("Specificity:", specificity)
Accuracy: 0.9375
Precision: 0.9752066115702479
Recall: 0.9365079365079365
Specificity: 0.94
In [ ]:
# a histogram to visualize the distribution of the match_similarity 
plt.figure(figsize=(8, 6))
sns.histplot(data=match_file, x="match_similarity", hue="expected_match", kde=False)
plt.title("Match Similarity Distribution of face_recognition open source library")
plt.show()
No description has been provided for this image

IV. Examples¶

1. Expected Match¶

For the first expected match comparision, I will examine its performance on Boyu's face and his aged version

In [ ]:
# 1. Load two images using load_image_file
face_file1 = "Boyu_Zheng.jpg"
face_file2 = "Boyu_Zheng_aged.jpg"
# 2. Compare the face_encodings similarity using face_distance
similarity = match_faces(face_file1, face_file2)
# Print the similarity score
print("The two faces are '{:.2f}%' similar".format(similarity))
The two faces are '63.12%' similar
In [ ]:
face_file1 = "./2024_students/Boyu_Zheng.jpg"
face_file2 = "./2024_students/Boyu_Zheng_aged.jpg"
display_compare_face(face_file1, face_file2)
No description has been provided for this image

For the second expected match comparision, I will examine Tianyi_Yin's face and her aged version

In [ ]:
# 1. Load two images using load_image_file
face_file1 = "Tianyi_Yin.jpg"
face_file2 = "Tianyi_Yin_aged.jpg"
# 2. Compare the face_encodings similarity using face_distance
similarity = match_faces(face_file1, face_file2)
# Print the similarity score
print("The two faces are '{:.2f}%' similar".format(similarity))
The two faces are '49.74%' similar
In [ ]:
face_file1 = "./2024_students/Tianyi_Yin.jpg"
face_file2 = "./2024_students/Tianyi_Yin_aged.jpg"
display_compare_face(face_file1, face_file2)
No description has been provided for this image

Though this is the same person, the model fails to recognize and the match similarity is below the threshold.

2. Expected Non-Match¶

For the first expected non-match comparision, I will examine the the facial comparision betweeen aged Boyu and aged Wei Tan

In [ ]:
# 1. Load two images using load_image_file
face_file1 = "Wei_Tan_aged.jpg"
face_file2 = "Boyu_Zheng_aged.jpg"
# 2. Compare the face_encodings similarity using face_distance
similarity = match_faces(face_file1, face_file2)
# Print the similarity score
print("The two faces are '{:.2f}%' similar".format(similarity))
The two faces are '48.93%' similar
In [ ]:
face_file1 = "./2024_students/Boyu_Zheng_aged.jpg"
face_file2 = "./2024_students/Wei_Tan_aged.jpg"
display_compare_face(face_file1, face_file2)
No description has been provided for this image

The match similarity is below the threshold, indicating the two faces are different, which is correct

For the second expected non-match facial comparision, I will examine Chenzhan Shen and the aged version of Xiaoya Luo

In [ ]:
# 1. Load two images using load_image_file
face_file1 = "Chengzhan_Shen.jpg"
face_file2 = "Xiaoya_Luo_aged.jpg"
# 2. Compare the face_encodings similarity using face_distance
similarity = match_faces(face_file1, face_file2)
# Print the similarity score
print("The two faces are '{:.2f}%' similar".format(similarity))
The two faces are '51.79%' similar
In [ ]:
face_file1 = "./2024_students/Chengzhan_Shen.jpg"
face_file2 = "./2024_students/Xiaoya_Luo_aged.jpg"
display_compare_face(face_file1, face_file2)
No description has been provided for this image